#include <stdlib.h>
#include <time.h>
#include "PSOGRunner.h"


PSOGRunner::PSOGRunner(double weight, double c1, double c2, int iterNum,double per, CoverageTable *ct)
	:percent(per),PSORunner(weight,c1,c2,iterNum,ct)
{
	table=ct;
}

PSOGRunner::~PSOGRunner()
{

}

void PSOGRunner::InitPara(vector<int>& pa)
{
	vector<int> tmp;
	for(int i=0;i<11;i++)
	{
		tmp.push_back(0);
	}
	for(int i=0;i<pa.size();i++)
	{
		para.push_back(tmp);
	}
}


int PSOGRunner::run(vector<vector<int>>& pop, vector<int>& pa)
{
	InitPara(pa);
	int ret;
	double tmp=GetCovPercent(pa);
	if(tmp<percent)
		ret=PSORunner::run(pop,pa);
	else
	{
		for(int i=0;i<pop[0].size();i++)
			pop[0][i]=0;
		run_greedy(pop[0],pa);
		ret=0;
	}
	para.clear();
	return ret;
}

void PSOGRunner::run_greedy(vector<int>& ca,vector<int>& pa)
{
	int tmp=GetMaxUnCov(pa);
	int FstPaIndex=tmp/11;
	int FstPaValue=tmp%11;
	vector<int> arr;
	GenRanArray(arr,ca.size(),FstPaIndex);
	ca[FstPaIndex]=FstPaValue;
	for(int i=1;i<arr.size();i++)
	{
		int max=0;
		int maxValue=0;
		for(int j=0;j<pa[arr[i]];j++)
		{
			int k=UnCoveredComb(arr,ca,i,j,FstPaIndex,FstPaValue);
			if(k>max)
			{
				max=k;
				maxValue=j;
			}
		}
		ca[arr[i]]=maxValue;
	}
}

int PSOGRunner::UnCoveredComb(vector<int>& arr, vector<int>& ca, int index, int value, int Fst, int FValue)
{
	int ret=0;
	int row,col;
	for(int i=0;i<index;i++)
	{
		if(arr[i]<arr[index])
		{
			row=arr.size()*arr[i]-(arr[i]*(arr[i]+1)>>1)+arr[index]-arr[i]-1;
			col=ca[arr[i]]*11+value;
		}
		else
		{
			row=arr.size()*arr[index]-(arr[index]*(arr[index]+1)>>1)+arr[i]-arr[index]-1;
			col=value*11+ca[arr[i]];
		}
		if(!table->CheckBit(row,col))
			ret++;
	}
	return ret;
}

int PSOGRunner::GetMaxUnCov(vector<int>& pa)
{
	int size=pa.size();
	for(int i=0;i<size-1;i++)
	{
		for(int j=i+1;j<size;j++)
		{
			int row=size*i-(i*(i+1)>>1)+j-i-1;
			for(int k=0;k<pa[i];k++)
			{
				for(int m=0;m<pa[j];m++)
					if(!table->CheckBit(row,k*11+m))
					{
						para[i][k]++;
						para[j][m]++;
					}
			}
		}
	}
	int max=0;
	int ret=0;
	for(int i=0;i<size;i++)
	{
		for(int j=0;j<pa[i];j++)
		{
			if(para[i][j]>max)
			{
				max=para[i][j];
				ret=i*11+j;
			}
		}
	}
	return ret;
}

void PSOGRunner::GenRanArray(vector<int>& arr, int size, int FIndex)
{
	for(int i=0;i<size;i++)
		arr.push_back(i);
	arr[0]=FIndex;
	arr[FIndex]=0;
	for(int i=1;i<size;i++)
	{
		srand(clock());
		int index=rand()%(size-i)+i;
		int tmp=arr[i];
		arr[i]=arr[index];
		arr[index]=tmp;
	}
}